package com.koicarp.university.graduate.service.service.graduateInfoManage.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.koicarp.university.graduate.service.dao.AcademyDao;
import com.koicarp.university.graduate.service.dao.ClassManageDao;
import com.koicarp.university.graduate.service.dao.GraduateStatusDao;
import com.koicarp.university.graduate.service.dao.SpecialityDao;
import com.koicarp.university.graduate.service.dto.bigView.*;
import com.koicarp.university.graduate.service.dto.dataCompare.EmployRateDto;
import com.koicarp.university.graduate.service.dto.dataCompare.SelectOptionDto;
import com.koicarp.university.graduate.service.entity.graduateInfoManage.GraduateStatus;
import com.koicarp.university.graduate.service.entity.schoolInfoManage.Academy;
import com.koicarp.university.graduate.service.entity.schoolInfoManage.ClassManage;
import com.koicarp.university.graduate.service.entity.schoolInfoManage.Speciality;
import com.koicarp.university.graduate.service.service.graduateInfoManage.Bayes2;
import com.koicarp.university.graduate.service.service.graduateInfoManage.EmployComparator;
import com.koicarp.university.graduate.service.service.graduateInfoManage.IGraduateStatusService;
import com.koicarp.university.graduate.service.vo.dataCompare.EmployRateVo;
import com.koicarp.university.graduate.service.vo.graduateInfoManage.TimeVo;
import com.koicarp.university.graudate.common.constant.BaseConstant;
import com.koicarp.university.graudate.common.utils.UniversityResponse;
import com.koicarp.university.graudate.common.utils.UniversityUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 【毕业生管理：毕业状态表(档案，就业状态)】(GraduateStatus)表服务实现类
 *
 * @author liutao
 * @since 2020-11-18 11:08:44
 */
@Service("graduateStatusService")
@Slf4j
@RequiredArgsConstructor
public class GraduateStatusServiceImpl extends ServiceImpl<GraduateStatusDao,GraduateStatus> implements IGraduateStatusService {

    private final GraduateStatusDao graduateStatusDao;

    private final AcademyDao academyDao;
    private final SpecialityDao specialityDao;
    private final ClassManageDao classManageDao;
    @Override
    public UniversityResponse getSelectOption() {
        UniversityResponse response = new UniversityResponse();
        response.code(BaseConstant.RESPONSE_CODE_SUCCESS_200);
        response.message(BaseConstant.RESPONSE_MESSAGE_OPR_SUCCESS);
        Academy academy = new Academy();
        List<Academy> academyList = academyDao.queryAll(academy);
        List<SelectOptionDto> optionDtos = new ArrayList<>();
        for (Academy a:academyList){
            SelectOptionDto selectOptionDto = new SelectOptionDto();
            selectOptionDto.setLabel(a.getAcademyName());
            selectOptionDto.setValue(a.getId());
            List<SelectOptionDto> children = new ArrayList<>();
            selectOptionDto.setChildren(children);
            optionDtos.add(selectOptionDto);
        }
        List<Speciality> specialityList = specialityDao.queryAll(new Speciality());
        for (Speciality s:specialityList){//专业
            for (SelectOptionDto select:optionDtos) {
                if (s.getAcademyId()==select.getValue()){//如果这个专业在这个学院里
                    SelectOptionDto selectOptionDto = new SelectOptionDto();
                    selectOptionDto.setLabel(s.getSpecialityName());
                    selectOptionDto.setValue(s.getId());
                    List<SelectOptionDto> children = new ArrayList<>();
                    selectOptionDto.setChildren(children);
                    select.getChildren().add(selectOptionDto);
                    break;
                }
            }
        }
        List<ClassManage> classManageList = classManageDao.queryAll(new ClassManage());
        for (ClassManage c:classManageList) {//班级层
            for (SelectOptionDto select:optionDtos){//学院层
                for (SelectOptionDto sp:select.getChildren()){//专业层
                    if (c.getSpecialityId()==sp.getValue()){
                        SelectOptionDto selectOptionDto = new SelectOptionDto();
                        selectOptionDto.setLabel(c.getClassName());
                        selectOptionDto.setValue(c.getId());
                        sp.getChildren().add(selectOptionDto);
                        break;
                    }
                }
            }
        }
        response.data(optionDtos);
        return response;
    }

    @Override
    public UniversityResponse predictionGraduate() {
        UniversityResponse response = new UniversityResponse();
        response.code(BaseConstant.RESPONSE_CODE_SUCCESS_200);
        response.message(BaseConstant.RESPONSE_MESSAGE_OPR_SUCCESS);
        List<BayesSampleDto> list = graduateStatusDao.selectForBayes();
        int employmentTrue = 0;
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getIfEmployment() == 1){
                employmentTrue++;
            }
        }
        double realRate = (double) employmentTrue*1.0/list.size()*1.0;

        Bayes2.init(list);
        List<BayesSampleDto> newList = graduateStatusDao.selectForBayesThisYear();
        int predictEmploymentTrue = 0;
        for (int i = 0; i < newList.size(); i++) {
            boolean employment = Bayes2.employment(newList.get(i));
            if (employment){
                predictEmploymentTrue++;
            }
        }
        double predictRate = (double) predictEmploymentTrue*1.0/newList.size()*1.0;

        EmploymentRateDto employmentRateDto = new EmploymentRateDto();
        employmentRateDto.setPredictRate(UniversityUtil.saveTwoDecimal(predictRate)*100);
        employmentRateDto.setRealRate(UniversityUtil.saveTwoDecimal(realRate)*100);
        response.data(employmentRateDto);
        return response;
    }

    @Override
    public UniversityResponse getStatusByTh() {
        UniversityResponse response = new UniversityResponse();
        response.code(BaseConstant.RESPONSE_CODE_SUCCESS_200);
        response.message(BaseConstant.RESPONSE_MESSAGE_OPR_SUCCESS);
        List<StatusByThDto> list = graduateStatusDao.selectStatusByTh();
        Date date = new Date();//获取当前时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, -4);
        Date nowYear = calendar.getTime();
        calendar.add(Calendar.YEAR,-1);
        Date lastYear = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat("yyyy");
        String last = format.format(lastYear);
        String now = format.format(nowYear);
        HashMap<String,Integer[]> nowMap = new HashMap<>();//数组第一个存数量，第二个存是否就业人数数量
        HashMap<String,Integer[]>  lastMap = new HashMap<>();
        for (StatusByThDto status: list) {
            if (status.getGraduateTh().equals(last)) {//去年毕业生所有就业情况
                boolean flag = false;
                for (HashMap.Entry<String, Integer[]> entry : lastMap.entrySet()) {//查找这个map里有没有这个专业
                    if (entry.getKey().equals(status.getAcademyName())) {//如果有value++
                        Integer[] integers = entry.getValue();
                        if (status.getIfEmployment() == 1) {
                            integers[1] = entry.getValue()[1] + 1;
                        }
                        flag = true;
                        integers[0] = entry.getValue()[0] + 1;
                        entry.setValue(integers);
                        break;
                    }
                }
                if (!flag) {
                    Integer[] integers = {1, 0};
                    if (status.getIfEmployment() == 1) {
                        integers[1] = 1;
                    }
                    lastMap.put(status.getAcademyName(), integers);
                }
            } else if (status.getGraduateTh().equals(now)) { //今年毕业生所有就业情况
                boolean flag = false;
                for (HashMap.Entry<String, Integer[]> entry : nowMap.entrySet()) {//查找这个map里有没有这个专业
                    if (entry.getKey().equals(status.getAcademyName())) {//如果有value++
                        flag = true;
                        Integer[] integers = entry.getValue();
                        integers[0] = entry.getValue()[0] + 1;
                        entry.setValue(integers);
                        if (status.getIfEmployment() == 1) {
                            integers[1] = entry.getValue()[1] + 1;
                        }
                        break;
                    }
                }
                if (!flag) {//没有找到插入该专业，数量初始化为0
                    Integer[] integers = {1, 0};
                    if (status.getIfEmployment() == 1) {
                        integers[1] = 1;
                    }
                    nowMap.put(status.getAcademyName(), integers);
                }
            } else {
                System.out.println("异常年份");
            }
        }
        List<UNCompareEmployDto> employDtoList = new ArrayList<>();

        for (HashMap.Entry<String, Integer[]> entry : nowMap.entrySet()){
            UNCompareEmployDto unCompareEmployDto= new UNCompareEmployDto();
            unCompareEmployDto.setAcademyName(entry.getKey());
            Integer[] value = entry.getValue();
            double nowRate = value[1]*1.0/value[0];
            BigDecimal bg = new BigDecimal(nowRate);
            double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()*100;//保留两位小数
            unCompareEmployDto.setNowYearEmployRate(f1);
            unCompareEmployDto.setNowYearEmploy(f1+"%");
            if (lastMap.get(entry.getKey()) != null){
                Integer[] value1 = lastMap.get(entry.getKey());
                double lastRate = value1[1]*1.0/value[0];
                bg = new BigDecimal(lastRate);
                double f2 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()*100;//保留两位小数
                unCompareEmployDto.setLastYearEmployRate(f2);
                unCompareEmployDto.setLastYearEmploy(f2+"%");
                double compareRate = (nowRate -lastRate)*1.0/nowRate;
                bg = new BigDecimal(compareRate);
                double f3 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()*100;//保留两位小数
                if (f3 >= 0){
                    unCompareEmployDto.setCompareRate("<span  class='colorGrass'>↑"+f3+"%</span>");
                }else{
                    unCompareEmployDto.setCompareRate("<span  class='colorRed'>↓"+f3+"%</span>");
                }
            }else{
                unCompareEmployDto.setCompareRate("<span  class='colorGrass'>↑0%</span>");
            }
            employDtoList.add(unCompareEmployDto);
        }
        Collections.sort(employDtoList,new EmployComparator());
        String[][] strArr = null;
        if (employDtoList.size() > 10){
            strArr  = new String[10][3];
            int i = 0;
            for (UNCompareEmployDto un :employDtoList){
                if(i>=10){
                    break;
                }
                strArr[i][0] = un.getAcademyName();
                strArr[i][1] = un.getNowYearEmploy();
                strArr[i][2] = un.getCompareRate();
                i++;
            }
        }else{
            strArr = new String[employDtoList.size()][3];
            int i = 0;
            for (UNCompareEmployDto un :employDtoList){
                strArr[i][0] = un.getAcademyName();
                strArr[i][1] = un.getNowYearEmploy();
                strArr[i][2] = un.getCompareRate();
                i++;
            }
        }
        response.data(strArr);
        return response;
    }

    @Override
    public UniversityResponse getEmployRate(EmployRateVo employRateVo) {
        UniversityResponse response = new UniversityResponse();
        response.code(BaseConstant.RESPONSE_CODE_SUCCESS_200);
        response.message(BaseConstant.RESPONSE_MESSAGE_OPR_SUCCESS);
        if (!UniversityUtil.isNotNull(employRateVo)){
            employRateVo = new EmployRateVo();
        }
        //格式化返回数据类型 近五年毕业生
        String nowYear = UniversityUtil.nowYear();
        employRateVo.setNowYear(nowYear);
        List<EmployRateDto> res = new ArrayList<>();
        int flag = 4;
        for (int i = 0; i < 5; i++) {
            EmployRateDto e = new EmployRateDto();
            int nowTh = Integer.parseInt(nowYear)-4;
            e.setGraduateTh(String.valueOf(nowTh-flag)+"届");
            flag--;
            res.add(e);
        }
        //下面是近五年人员数量查找
        List<EmployRateDto> allList = graduateStatusDao.selectEmployRate(employRateVo);
        for (EmployRateDto e: allList) {
            for (EmployRateDto r: res) {
                if(r.getGraduateTh().equals(e.getGraduateTh()+"届")){
                    r.setGraduateNum(e.getGraduateNum());
                }
            }
        }
        //下面是近五年就业人员数量查找 以及求就业率
        employRateVo.setIfEmployment(1);
        List<EmployRateDto> employList = graduateStatusDao.selectEmployRate(employRateVo);
        for (EmployRateDto e: employList) {
            for (EmployRateDto r: res) {
                if(r.getGraduateTh().equals(e.getGraduateTh()+"届")){
                    double tmp = e.getGraduateNum()/r.getGraduateNum();
                    r.setGraduateNum(UniversityUtil.saveTwoDecimal(tmp));
                }
            }
        }
        response.data(res);
        return response;
    }

    @Override
    public UniversityResponse countEnterHighByYear() {
        UniversityResponse response = new UniversityResponse();
        response.code(BaseConstant.RESPONSE_CODE_SUCCESS_200);
        response.message(BaseConstant.RESPONSE_MESSAGE_OPR_SUCCESS);
        String nowYear = UniversityUtil.nowYear();
        List<EnterHighDto> res = new ArrayList<>();
        int beginTime = Integer.parseInt(nowYear)-4;//2016
        int endTime = beginTime - 4;
        TimeVo t = new TimeVo();
        t.setBeginTime(String.valueOf(beginTime));
        t.setEndTime(String.valueOf(endTime));
        int flag = 4;
        for (int i = 0; i < 5; i++) {
            EnterHighDto enterHighDto = new EnterHighDto();
            enterHighDto.setGraduateTh(String.valueOf(beginTime-flag));
            enterHighDto.setHighNum(0);
            res.add(enterHighDto);
            flag--;
        }
        List<EnterHighDto> list = graduateStatusDao.countEnterHighByYear(t);
        for (EnterHighDto e: list) {
            for (EnterHighDto enterHighDto: res) {
                if (e.getGraduateTh().equals(enterHighDto.getGraduateTh())){
                    enterHighDto.setHighNum(e.getHighNum());
                }
            }
        }
        response.data(res);
        return response;
    }


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public UniversityResponse queryById(Integer id) {
        UniversityResponse response = new UniversityResponse();
        response.code(BaseConstant.RESPONSE_CODE_SUCCESS_200);
        response.message(BaseConstant.RESPONSE_MESSAGE_OPR_SUCCESS);
        GraduateStatus status = graduateStatusDao.queryById(id);
        response.data(status);
        return response;
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<GraduateStatus> queryAllByLimit(int offset, int limit) {
        return this.graduateStatusDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param graduateStatus 实例对象
     * @return 实例对象
     */
    @Override
    public GraduateStatus insert(GraduateStatus graduateStatus) {
        this.graduateStatusDao.insert(graduateStatus);
        return graduateStatus;
    }

    /**
     * 修改数据
     *
     * @param graduateStatus 实例对象
     * @return 实例对象
     */
//    @Override
//    public GraduateStatus update(GraduateStatus graduateStatus) {
//        this.graduateStatusDao.update(graduateStatus);
//        return this.queryById(graduateStatus.getId());
//    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.graduateStatusDao.deleteById(id) > 0;
    }
}